package conf

import (
	"bytes"
	"embed"
	"fmt"
	"gitee.com/llakcs/agile-go/config"
	"gitee.com/llakcs/agile-go/log"
	"gitee.com/llakcs/aglie-layout/data/ds"
	"io/fs"
	"path/filepath"
	"regexp"
	"strings"
	"time"
)

type Config struct {
	Logf   *LogConf    `mapstructure:"log"`
	Data   *DataConf   `mapstructure:"data"`
	Server *ServerConf `mapstructure:"server"`
	App    *AppConf    `mapstructure:"application"`
}

type AppConf struct {
	AppName string `mapstructure:"name"`
	AppID   string `mapstructure:"id"`
	AppVer  string `mapstructure:"version"`
}

type DataConf struct {
	DataSource *DataSourceConf `mapstructure:"database"`
	RedisConf  *RedisConf      `mapstructure:"redis"`
	MqConf     *RabbitMqConf   `mapstructure:"rabbitmq"`
}

type ServerConf struct {
	HttpConf *HttpConf `mapstructure:"http"`
	GrpcConf *GrpcConf `mapstructure:"grpc"`
}

type HttpConf struct {
	Addr    string        `mapstructure:"addr"`
	Timeout time.Duration `mapstructure:"timeout"`
}

type GrpcConf struct {
	Addr    string        `mapstructure:"addr"`
	Timeout time.Duration `mapstructure:"timeout"`
}

func InitConfig(flagconf string, res embed.FS) *config.Configure {
	log.Info("The program is loading configuration")
	var cf *config.Configure
	has, cerr := checkConfFiles(flagconf)
	if cerr != nil || !has {
		log.Info("Load resource file default configuration")
		//找不到配置目录下的文件,读取程序默认配置
		cf = config.NewConfig()
		b, err := res.ReadFile("resources/configs/config.yaml")
		if err != nil {
			panic(err)
		}
		cf.V.SetConfigType("yaml")
		cf.V.ReadConfig(bytes.NewBuffer(b))
		cf.V.AutomaticEnv()
		cf.LoadALLValue()
	} else {
		log.Info("Load the configuration file for the preset directory")
		//开始扫描配置目录下的配置文件
		cf = config.NewConfig(
			config.WithConfigPath(flagconf),     //配置所在地址
			config.WithAllowedExtensions("yml")) //配置支持的格式
		//开始加载配置
		if err := cf.Load(); err != nil {
			panic(err)
		}
	}
	return cf
}

// 扫描整体配置
func ScanConfig(cf *config.Configure) *Config {
	//扫描整体配置
	conf := &Config{
		Logf: nil,
		Data: nil,
	}
	err := cf.Scan(conf)
	if err != nil {
		fmt.Println(err)
	}
	return conf
}

// 读取sql脚本
func LoadSqlScript(res embed.FS) {
	log.Info("Load sql script")
	if ds.GetDS() == nil {
		//如果数据源是空就返回
		return
	}
	// 遍历数据库脚本根目录下的所有文件和子目录
	err := fs.WalkDir(res, "resources/sql/mysql", func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		// 如果不是目录，则可以进一步处理文件（例如读取内容）
		if !d.IsDir() {
			// 这里可以添加读取或处理文件的代码
			log.Info("Load sql：", path)
			fileData, err := fs.ReadFile(res, path)
			if err != nil {
				return err
			}
			//根据分隔符进行处理脚本
			sqlTmp := string(fileData)
			handlerSqlLines(sqlTmp)
		}
		return nil
	})

	if err != nil {
		fmt.Printf("Error walking through embedded files: %v\n", err)
	}
}

// 处理脚本
func handlerSqlLines(sql string) {
	//cleanedSql := strings.ReplaceAll(sql, "[", "")
	//cleanedSql = strings.ReplaceAll(cleanedSql, "]", "")
	regex := regexp.MustCompile(`(--.*)|\[|\]`)
	cleanSQL := regex.ReplaceAllString(sql, "")
	sqlParts := strings.Split(cleanSQL, "//")
	for _, line := range sqlParts {
		if !isEmptyString(line) {
			ds.GetDS().Exec(line)
		}
	}
}

func isEmptyString(str string) bool {
	return strings.TrimSpace(str) == ""
}

// CheckConfFiles 检查指定目录下是否存在具有yml或yaml后缀的文件。
func checkConfFiles(dirPath string) (bool, error) {
	var found bool
	err := filepath.WalkDir(dirPath, func(path string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if !d.IsDir() {
			ext := strings.ToLower(filepath.Ext(path))
			if ext == ".yml" || ext == ".yaml" {
				found = true
				return fmt.Errorf("found") // 一旦找到，提前终止遍历
			}
		}
		return nil
	})

	if err != nil && err.Error() != "found" {
		return false, err
	}

	return found, nil
}
